package com.appsindy.common.util;

import com.appsindy.common.exception.FTPConnectionNotFoundException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPConnectionClosedException;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

public class FTPUtil {
    Logger  logger = Logger.getLogger(FTPUtil.class.getPackage().getName());
    
    public static final int BINARY_FILE = FTPClient.BINARY_FILE_TYPE;
    public static final int ASCII_FILE = FTPClient.ASCII_FILE_TYPE;
    private FTPClient ftp;
    
    public FTPUtil() {
    }

    public void open(String server, String username, String password) throws Exception {
        open(server, 21, username, password);
    }
    
    public void open(String server, int port, String username, String password) throws Exception {
        ftp = new FTPClient();
        try {
            int reply;
            ftp.connect(server, port);
            logger.info("Connected to " + server + ".");
            
            // After connection attempt, you should check the reply code to verify
            // success.
            reply = ftp.getReplyCode();
            
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                logger.error("FTP server refused connection.");
                throw new Exception("FTP server refused connection.");
            }
            // login to ftp server
            if (!ftp.login(username, password)) {
                ftp.logout();
                logger.error("Login fail.");
                throw new Exception("Login fail.");
            }
            
            // set default to ascii type
            ftp.setFileType(ASCII_FILE);
            
            // Use passive mode as default because most of us are
            // behind firewalls these days.
            ftp.enterLocalPassiveMode();
        } catch (FTPConnectionClosedException e) {
            logger.error("Server closed connection.");
            throw new Exception("Server closed connection.");
        } catch (IOException e) {
            logger.error("Could not connect to server. " + e.getMessage());
            throw new Exception("Could not connect to server. " + e.getMessage());
        }
        logger.info("Remote system is " + ftp.getSystemName());
    }
    
    public void put(String local) throws FTPConnectionNotFoundException, Exception {
        checkFtpOpen();
        logger.info("Putting file '" + local + "'.");
        String remote = getFileName(local);
        InputStream input = new FileInputStream(local);
        put(input, remote);
    }
    
    public void put(String local, String remote) throws FTPConnectionNotFoundException, Exception {
        checkFtpOpen();
        logger.info("Putting file '" + local + "' to '" + remote + "'");
        InputStream input = new FileInputStream(local);
        put(input, remote);
    }
    
    public void put(InputStream input, String remote) throws FTPConnectionNotFoundException, Exception {
        checkFtpOpen();
        try {
            ftp.storeFile(remote, input);
            input.close();
        } catch (FTPConnectionClosedException e) {
            logger.error("Server closed connection.");
            throw new Exception("Server closed connection.");
        } catch (IOException e) {
            logger.error("Could not connect to server. " + e.getMessage());
            throw new Exception("Could not connect to server. " + e.getMessage());
        }
    }
    
    public void get(String local, String remote) throws FTPConnectionNotFoundException, Exception {
        checkFtpOpen();
        
        OutputStream output;
        
        try {
            output = new FileOutputStream(local);
            
            ftp.retrieveFile(remote, output);
            
            output.close();
        } catch (FTPConnectionClosedException e) {
            logger.error("Server closed connection.");
            throw new Exception("Server closed connection.");
        } catch (IOException e) {
            logger.error("Could not connect to server. " + e.getMessage());
            throw new Exception("Could not connect to server. " + e.getMessage());
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException f) {
                    // do nothing
                }
            }
        }
    }
    
    public void setFileType(int type) throws FTPConnectionNotFoundException, Exception {
        checkFtpOpen();
        ftp.setFileType(type);
    }
    
    private void checkFtpOpen() throws FTPConnectionNotFoundException {
        if (ftp == null || !ftp.isConnected()) {
            throw new FTPConnectionNotFoundException();
        }
    }
    
    public void close() {
        if (ftp != null) {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ex) {
                    //do nothing
                }
            }
        }
    }
    
    public static String getFileName(String filepath) {
        return (filepath ==null) ? null :
            filepath.substring(filepath.lastIndexOf(File.separator) + 1);
    }
    
    protected void finalize() throws Throwable {
        super.finalize();
        close();
    }
    
}
